/** @jsxImportSource @emotion/react */
import {jsx,  css } from "@emotion/react";
import * as React from "react";
import PropTypes from "prop-types";
import { Layer } from "./Layer";
import { useTheme } from "./Theme/Providers";
import {ElementType} from "react";
// import {Layer, useTheme,} from "customize-easy-ui-component";
import {useMeasure} from "./Hooks/use-measure";
import {usePressable} from "./Hooks/pressable-hook";
import cx from "classnames";
import {safeBind} from "./Hooks/compose-bind";
import {Spinner} from "./Spinner";
import {IconWrapper} from "./IconWrapper";
import {ButtonProps, buttonReset, getHeight} from "./Button";
// import { useMeasure, } from "customize-easy-ui-component/esm/Hooks/use-measure";

type SectionTypeVariants = "TableHead" | "TableBody" | "TableFoot";

interface TableSectionContextType {
    type: SectionTypeVariants;
    /**限制一行 tr 的默认高度，但是内容高度超出的话会失效*/
    rheight?: number;
}

//没有对外输出TableSectionContext的；无法import {TableSectionContext} from "customize-easy-ui-component";
const TableSectionContext = React.createContext<TableSectionContextType>({
    type: "TableHead",
});

interface TableLayContextType {
    /**小屏幕 默认不显示左右的边框*/
    lrBoder?: boolean;
    /**打印预览的或真实打印的场合：要求高度方向也得执行紧凑做法的？  高度方向的；*/
    vtight?: boolean;
    /**宽度布局非常拥挤吗，根据实际宽度阈值比对的；若实际宽度 少于miniw的 就开启紧凑模式。 水平方向的。*/
    hcompact?: boolean;
}
const TableLayContext = React.createContext<TableLayContextType>({
    lrBoder: false,
    vtight: false,
    hcompact: false,
});

//旧版本的TableOld才需要使用到的 context变量； 新版本已经改成参数适应;
/** @Deprecated
 * */
const TableContext = React.createContext({ fixed: false });

/**
 * A Table provides a useful abstraction for managing rows and columns.
 */

interface TableProps extends React.HTMLAttributes<HTMLTableElement> {
    /** An optional minimum width for table content.
     * 配置表格的最小宽度，小于它就启用水平滚动条。 举例：minWidth=css 单位。
     *  */
    minWidth?: string;
    /** An optional array of fixed layout widths for each column
     * 非打印场景的必须看fixed； 打印场景优先使用printColWidth；若这两者都没定义那就是系统自动的 走了浏览器默认机制。
     * 百分比% 和数值px两种形式。 举例：fixed={["8%","23%","%","12%"] }  printColWidth={["60","156","700","80"]}
     * */
    fixed?: string[];
    //打印场景才采用的： 敲定的列宽on printer case,set just as fixed  above; 3种形式[pixels, %, relative_length%]; pixels单位是px;
    /**允许打印时刻特别调整各列的宽度比例
     * 就算不是百分比的配置 也即用pixels的：最后也是同义转换百分比处理
     * */
    printColWidth?: string[];
    //为了处理这个毛病：用100%宽度+打印时若没有勾选页眉页脚的，可能右边表格边线被裁减不见。Chrome版本116.0.5845.118正常。而117.0.5938.92版本Chrome有问题不勾选页眉页脚的就被截切。
    // prevPrune?: boolean; 改成了用全局的<Global styles={{ body: { margin: 0, "@media print": { margin: '0 1px 0 0'},},样式来解决这个BUG问题了。
    //约定打印的合计总宽度= px单位的，优先于printColWidth，打印各列宽度比例按照printColWidth比例映射，或者没有printColWidth就按照fixed比例映射；
    // agptWidth?: number;
    //嵌套表格，宽度被父辈Table做了约定的，并且要求自动和父辈同宽度的合并边线的。
    // nested?: boolean;
    /**打印预览的或真实打印的场合：要求高度方向也得执行紧凑做法的？  TD/Row 高度方向的紧凑；
     * 正常的显示或导航点击每一行需要的情形就不要开启紧凑，避免高度压缩过度。
     * 默认不紧凑。*/
    tight?: boolean;
    /**宽度布局非常拥挤吗，根据实际宽度阈值比对的；若Table实际宽度px数 少于miniw的 就开启紧凑模式。 TD的 padding 的是否省略。
     * 默认不紧凑：有padding的。*/
    miniw?: number;
    /**手机小屏幕的情况，默认不显示左右的边框；
     * */
    lrBoder?: boolean;
}


type  LayoutValType= "fixed" | undefined;
type  ColgroupWidthType= string[] | number[];

/**
 支持打印自适应，支持手机自适应。 Table不适合小屏幕和列数较多的字段长度不统一可能较长的这些情形。
 @param fixed:非打印的布局各列尺寸设置，一般是百分比比例。 若fixed不设置会自动调整的。
 @param printColWidth:真实打印或打印预览情况的布局各列尺寸，一般是px数值。合计一般：A4竖版就是合计718px，超过了会自动缩小字体。
 若printColWidth没必要一定要准确配置的呢？嵌套表格的上一级宽度已经是父辈Table做了约定的？
 @param agptWidth: 约定打印的合计总宽度，优先于printColWidth，打印各列宽度比例按照printColWidth比例映射，或者没有printColWidth就按照fixed比例映射；
  对于A4 竖版打印 windows chrome正好 718 px的不会缩小。
  嵌套在内部的表格 设置agptWidth={0} 可以自适应宽度；
 @param nested:嵌套表格，宽度被父辈Table做了约定的，并且要求自动和父辈同宽度的合并边线的。agptWidth若没有设置的就按比例分配100%宽度。
 文书正规视图的应该配置fixed或printColWidth，完全自适应也不友好：随数据长度变动各列位置可能不恰当！最好配置各列比例数。
 【打印问题】因为加了miniw参数可能导致的测量div的宽度产生动态样式，会导致早就在动态样式生成之前就敲定打印页数。
 若在<TableBody css={{height:'120px'}}>做限制的只能首先内部的tr td 有空间情况下只能大不能比内部tr td的合计高度还要小的。
 */
export const Table = ({
                          children,
                          minWidth,
                          fixed,
                          printColWidth,
                          lrBoder,
                          tight,
                          miniw,
                          ...other
                      }: TableProps) => {
    const theme = useTheme();
    const refTbl = React.useRef<HTMLDivElement>(null);
    const widthTbl= useMeasure(refTbl)?.width || 0;
    const [printLayout, printFinWid] =React.useMemo(() => {
        let config=printColWidth? printColWidth : fixed;
        if(!config)  return [undefined, undefined];
        if(!printColWidth)  return ["fixed", undefined];
        //2种形式[pixels, %, relative_length%]不能混和配置的吧；
        let percent=false;
        let pcs=config.map((width, i) => {
            if(!percent && width.endsWith('%'))   percent=true;
            const strnum = width.replace(/[%]/g, '');
            return Number(strnum);
        });
        let remain=-1;   //配置数组当中唯一一个的 %位置点 的索引；
        pcs.forEach((wd, index, array) => {
            if(wd<=0){
                array[index]=0;
                if(percent && array[index]===0)  remain=index;
            }
        });
        let totals= pcs.reduce(function (total, value) {
            return total + value;
        }, 0);
        if(percent && remain>=0){
            if(totals<100){
                pcs[remain]=100-totals;      //分配唯一个的 %位点
                totals=100;
            }
        }
        // if(!nested && agptWidth<=0)      //也允许agptWidth==0来纠正的
        //     return ["fixed", pcs];
        //重新计算比例：
        let finalPc=pcs.map((oldpc, i) => {
            let pctv=100*oldpc/totals;
            return `${Math.round(pctv*100)/100}%`;
            //若不加上‘%’且也不乘以100倍数，可能导致最后一列的误差非常巨大的！！
        });
        return ["fixed", finalPc];      //嵌套 设置agptWidth={0}
        //不能用px数字直接<colgroup<col配置，列数多了就会很容易出现实际上竟然超出限制px数，导致边线会丢失。 【只好】改成百分比做法+上级来设置width: 718px;
    }, [printColWidth,fixed])  as [LayoutValType, ColgroupWidthType];

    return (
        <div  ref={refTbl}
            css={{
                width: "100%",
                display: "block",
                overflowX: minWidth ? "auto" : "initial"
            }}
        >
            <table
                css={{
                    borderSpacing: 0,
                    borderCollapse: "separate",
                    width: "100%",
                    fontFamily: theme.fonts.base,
                    WebkitAppearance: "none",
                    WebkitFontSmoothing: "antialiased",
                    display: "table",
                    minWidth,
                    tableLayout: fixed ? "fixed" : undefined,
                    "@media print": {
                        tableLayout: printLayout,
                        //width: prevPrune? 'unset' : undefined, 去掉了100%页不好啊：因不能够铺满纸张的全宽度，需要非常准确的尺寸配置才行。对付浏览器的BUG？
                        //width: !nested? `${agptWidth}px` : undefined,  没必要限制死的；
                    }
                }}
                {...other}
            >
                { printLayout &&
                    <>
                        { fixed &&
                            <colgroup
                                css={{
                                    "@media print": {
                                        display: printFinWid? 'none' : undefined,
                                    },
                                }}
                            >
                                {fixed?.map((width, i) => {
                                    return <col key={i} width={width} />;
                                })}
                            </colgroup>
                        }
                        { printFinWid &&
                            <colgroup
                                css={{
                                    "@media not print": {
                                        display: 'none',
                                    },
                                }}
                            >
                                {printFinWid.map((width, i) => {
                                    return <col key={i} width={width} />;
                                })}
                            </colgroup>
                        }
                    </>
                }

                <TableLayContext.Provider value={{
                    lrBoder,
                    vtight: tight,
                    hcompact: (widthTbl>0 && (miniw!)>0 && widthTbl<(miniw!)),
                }}>
                    {children}
                </TableLayContext.Provider>

            </table>
        </div>
    );
};


// Table.propTypes = {
//     minWidth: PropTypes.string,
//     fixed: PropTypes.arrayOf(PropTypes.any),
//     printColWidth: PropTypes.arrayOf(PropTypes.any),
//     children: PropTypes.node
// };

/**
 * A TableHead is used to render column labels in a table.
 */

// type TableHeadProps = React.HTMLAttributes<HTMLTableSectionElement>;
interface TableHeadProps extends React.HTMLAttributes<HTMLTableSectionElement> {
    rheight?: number;
}
/**就算TableBody在DOM流位置比TableHead靠前，也TableHead表现一样；多个Table嵌套的打印断页拆分的也类似会有多个TableHead在页首部处留存。
 * */
export function TableHead({ children,rheight, ...other }: TableHeadProps) {
    return (
        <thead
            css={{
                display: "table-header-group"
            }}
            {...other}
        >
        <TableSectionContext.Provider value={{ type: "TableHead",
            rheight
        }}>
            {children}
        </TableSectionContext.Provider>
        </thead>
    );
}

interface TableRowProps extends React.HTMLAttributes<HTMLTableRowElement> {
    /** A callback when a row is selected */
    onClick?: () => void;
}

export const TableRow = ({
                             onClick,
                             children,
                             ...other
                         }:TableRowProps) => {
    const theme = useTheme();
    const { type: tableSectionType,rheight } = React.useContext(TableSectionContext);
    const { vtight } = React.useContext(TableLayContext);

    const buttonProps = onClick
        ? {
            role: "button",
            tabIndex: 0
        }
        : {};

    const height=rheight? rheight : ( tableSectionType === "TableHead" ? (vtight? 25 : 31) : (vtight? 33 : 49) );

    return (
        <tr
            onClick={onClick}
            css={{
                height: `${height}px`,
                display: "table-row",
                outline: "none",
                verticalAlign: "middle",
                cursor: onClick ? "pointer" : "default",
                ":hover": {
                    background: onClick ? theme.colors.background.tint1 : "none"
                }
            }}
            {...buttonProps}
            {...other}
        >
            {children}
        </tr>
    );
};

// TableRow.propTypes = {
//     onClick: PropTypes.func,
//     children: PropTypes.node
// };

/**
 * Cell TableCell, used for both <td> and <th> elements.
 * textAlign: "justify" 导致字间距自动变大，感觉不规整，不如textAlign: "left"。
 */

const tableCellAlignments = {
    right: css({
        textAlign: "right",
        flexDirection: "row-reverse"
    }),
    left: css({
        textAlign: "left"
    }),
    center: css({
        textAlign: "center"
    }),
    justify: css({
        textAlign: "justify"
    })
};

type AlignCellType = "right" | "left" | "center" | "justify";

type tableCellVariants = "head" | "body";

type TableCellBaseProps = React.ThHTMLAttributes<HTMLTableHeaderCellElement> &
    React.TdHTMLAttributes<HTMLTableDataCellElement> & React.HTMLProps<TableCellBaseProps>;

interface TableCellProps extends TableCellBaseProps {
    align?: AlignCellType;
    //align?: keyof typeof tableCellAlignments;
    variant?: tableCellVariants;
    ellipsis?: boolean;
    //原本?:React.ElementType<TableCellBaseProps>;
    component?: React.ElementType;
    /**是否<td><th>在打印之中，遇到了分页位置应该允许断开。浏览器原先默认是断开的。这里改成默认不能拆分开的。
     * split=true就是允许打印拆分断开。
     * */
    split?: boolean;
}

/** @Deprecated
 * 旧版本的Cell组件，新版本改用Cell; 两个版本的样式不一样
 */
export const TableCell = ({
                              align = "left",
                              variant,
                              component,
                              ellipsis,
                              children,
                              ...other
                          }:TableCellProps) => {
    const theme = useTheme();
    const { type: tableSectionType } = React.useContext(TableSectionContext);

    const Component =
        component || (tableSectionType === "TableHead" ? "th" : "td");

    const type = variant || (tableSectionType === "TableHead" ? "head" : "body");

    return (
        <Component
            css={[
                {
                    zIndex: 4,
                    position: "relative",
                    borderBottom: "1px solid",
                    borderColor:
                        tableSectionType === "TableBody"
                            ? theme.colors.border.muted
                            : theme.colors.border.default,
                    display: "table-cell",
                    padding: `${theme.spaces.xs} ${theme.spaces.sm}`,
                    [theme.mediaQueries.lg]: {
                        paddingLeft: theme.spaces.md,
                        paddingRight: theme.spaces.md
                    },
                    ":last-child": {
                        paddingRight: theme.spaces.md
                    }
                },
                ellipsis && {
                    whiteSpace: "nowrap",
                    textOverflow: "ellipsis",
                    overflow: "hidden"
                },
                type === "head"
                    ? {
                        fontWeight: 500,
                        fontSize: theme.fontSizes[0],
                        color: theme.colors.text.heading
                    }
                    : {
                        fontWeight: 400,
                        fontSize: theme.fontSizes[0],
                        color: theme.colors.text.default
                    },
                tableCellAlignments[align],
                {
                }
            ]}
            scope="col"
            {...other}
        >
            {children}
        </Component>
    );
};

// TableCell.propTypes = {
//     align: PropTypes.oneOf(["right","left","center","justify"] as AlignCellType[]),
//     variant: PropTypes.oneOf(["body", "head"] as tableCellVariants[]),
//     // component: PropTypes.element,
//     ellipsis: PropTypes.bool,
//     children: PropTypes.node
// };
/*可以通过interface来约定react组件props，还有必要用react的propTypes吗？
2个会报类型错误？TableCell.propTypes {align: PropTypes.oneOf( ； component: PropTypes.elementType,}
 这个地方似乎是打包层次用到的。  报错？只好删除了。
 可以只用typescript进行验证，也可以只用prop-types进行验证，也可以两者混搭进行验证，这个并没用严格限制。
首先不管用typescript，还是prop-types，都只在开发模式下进行检查。 PropTypes是组件接收prop的约束。
*/

/**
 * 新版 TableCell 组件，支持手机上作表格形式的报告，支持打印。
 * 做报表用的样式, CCell, RCell类似 Cell,就差align格式;
 * 旧版本请用TableCell组件,两个版本的样式不一样
 * 前提：每一行的要么是td 要么是th，不要混合td和th;
 * @param split:允许打印拆分这个<td>吗？ component设置要注意 统一一行的td 要么th。 TableSectionContext须用同一个实例的才能正常；
 */
export const Cell = ({
                         align = "left",
                         variant,
                         component,
                         ellipsis,
                         children,
                         split=false,
                         ...other
                     }:TableCellProps) => {
    const theme = useTheme();
    const { type: tableSectionType } = React.useContext(TableSectionContext);
    const { lrBoder,hcompact } = React.useContext(TableLayContext);

    const Component =
        component || (tableSectionType === "TableHead" ? "th" : "td");

    const type = variant || (tableSectionType === "TableHead" ? "head" : "body");

    return (
        <Component
            css={[
                {
                    zIndex: 4,
                    position: "relative",
                    border: "1px solid",
                    display: "table-cell",
                    padding: hcompact? `${theme.spaces.xs} 0` : `${theme.spaces.xs} ${theme.spaces.xs}`,
                    wordBreak: 'break-word',
                },
                ellipsis && {
                    whiteSpace: "nowrap",
                    textOverflow: "ellipsis",
                    overflow: "hidden"
                },
                type === "head"
                    ? {
                        fontWeight: 500,
                        fontSize: theme.fontSizes[0],
                        color: theme.colors.text.heading
                    }
                    : {
                        fontWeight: 400,
                        fontSize: theme.fontSizes[0],
                        color: theme.colors.text.default
                    },
                tableCellAlignments[align],
                lrBoder? {} :
                    {
                        [theme.mediaQueries.phone]: {
                            ":first-of-type": {
                                borderLeft: "none"       //每一行tr底下要么是td要么是th不要混合td和th;
                            },
                            ":last-of-type": {
                                borderRight: "none"
                            }
                        }
                    },
                {
                    "@media print": {
                        pageBreakInside: split? undefined : 'avoid',
                    }
                }
            ]}
            scope="col"
            {...other}
        >
            {children}
        </Component>
    );
};

/**可支持传入 ref 控制的 <td/> <th>。
 */
export const CellRefComp =
    ({
            align = "center",
            variant,
            component,
            ellipsis,
            children,
            split=false,
            ref,
            ...other
        }: TableCellProps
    ) => {
        const theme = useTheme();
        const { type: tableSectionType } = React.useContext(TableSectionContext);
        const { lrBoder,hcompact } = React.useContext(TableLayContext);

        const Component =
            component || (tableSectionType === "TableHead" ? "th" : "td");

        const type = variant || (tableSectionType === "TableHead" ? "head" : "body");

        return (
            <Component
                css={[
                    {
                        zIndex: 4,
                        position: "relative",
                        border: "1px solid",
                        display: "table-cell",
                        padding: hcompact? `${theme.spaces.xs} 0` : `${theme.spaces.xs} ${theme.spaces.xs}`,
                        wordBreak: 'break-word',
                    },
                    ellipsis && {
                        whiteSpace: "nowrap",
                        textOverflow: "ellipsis",
                        overflow: "hidden"
                    },
                    type === "head"
                        ? {
                            fontWeight: 500,
                            fontSize: theme.fontSizes[0],
                            color: theme.colors.text.heading
                        }
                        : {
                            fontWeight: 400,
                            fontSize: theme.fontSizes[0],
                            color: theme.colors.text.default
                        },
                    tableCellAlignments[align],
                    lrBoder? {} :
                        {
                            [theme.mediaQueries.phone]: {
                                ":first-of-type": {
                                    borderLeft: "none"       //每一行tr底下要么是td要么是th不要混合td和th;
                                },
                                ":last-of-type": {
                                    borderRight: "none"
                                }
                            }
                        },
                    {
                        "@media print": {
                            pageBreakInside: split? undefined : 'avoid',
                        }
                    }
                ]}
                scope="col"
                {... ( safeBind( { ref }, other) ) }
            >
                {children}
            </Component>
        );
    };

/**
 * TableBody - indicates the body (and scrollable) portion of our table.
 */

// type TableBodyProps = React.HTMLAttributes<HTMLTableSectionElement>;
interface TableBodyProps extends React.HTMLAttributes<HTMLTableSectionElement> {
    /** tr 行高约定为 多少px
     * 注意rheight的优先级别比Table的参数tight更高的！
     * */
    rheight?: number;
}
export function TableBody({ children,rheight, ...other }: TableBodyProps) {
    return (
        <tbody
            css={{
                display: "table-row-group"
            }}
            {...other}
        >
        <TableSectionContext.Provider value={{ type: "TableBody",
            rheight
        }}>
            {children}
        </TableSectionContext.Provider>
        </tbody>
    );
}

/**
 * An ExpandingRow displays additional content about the row when clicked.
 */

interface ExpandingRowProps {
    /** The expanded content to show when the user selects the row */
    content: (close: () => void) => React.ReactNode | React.ReactNode;
    children: React.ReactNode;
}

export const ExpandingRow = ({
                                 content,
                                 children
                             }:ExpandingRowProps) => {
    const theme = useTheme();
    const [selected, setSelected] = React.useState(false);

    function close() {
        setSelected(false);
    }

    function open() {
        setSelected(true);
    }

    return (
        <TableBody>
            <TableRow onClick={open}>{children}</TableRow>
            {selected && (
                <tr css={{ display: "table-row", height: "100px" }}>
                    <td
                        colSpan={React.Children.count(children)}
                        css={{
                            borderBottom: 0,
                            width: "inherit",
                            padding: 0,
                            position: "relative"
                        }}
                    >
                        <div
                            css={{
                                zIndex: 3,
                                width: "inherit",
                                position: "relative",
                                paddingBottom: "24px"
                            }}
                        >
                            <div
                                css={{
                                    position: "relative",
                                    whiteSpace: "normal",
                                    height: "auto",
                                    display: "block",
                                    paddingTop: "24px"
                                }}
                            >
                                {typeof content === "function" ? content(close) : content}
                            </div>
                        </div>
                        <Layer
                            css={{
                                position: "absolute",
                                top: "-49px",
                                left: "-16px",
                                right: "-16px",
                                borderRadius: theme.radii.md,
                                bottom: 0,
                                zIndex: 2
                            }}
                        >
                            {null}
                        </Layer>
                    </td>
                </tr>
            )}
        </TableBody>
    );
};

//被删除的部分 xxx.propTypes = {  };  是和rollup.js相关，一个模块打包工具/发布工具库，使用ES6的模块标准。

// ExpandingRow.propTypes = {
//     //content: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
//     children: PropTypes.node
// };


/**
 大量重复的组件标签，简化: CCell代表居中显示的Cell
 */
export const CCell =
    (
        {
            align = "center",
            variant,
            component,
            ellipsis,
            children,
            ...other
        }:TableCellProps) =>
    {

        return (
            Cell({
                align,
                variant,
                component,
                ellipsis,
                children,
                ...other
            })
        );
    };


/**做点简化，免得看起来是一大堆重复性质代码：
 * 代表靠右边 显示的Cell
 */
export const RCell =
    (
        {
            align = "right",
            variant,
            component,
            ellipsis,
            children,
            ...other
        }:TableCellProps) =>
    {

        return (
            Cell({
                align,
                variant,
                component,
                ellipsis,
                children,
                ...other
            })
        );
    };

/**就算TableBody在DOM流位置比TableHead靠前，也TableHead表现一样；多个Table嵌套的打印断页拆分的也类似会有多个TableHead在页首部处留存。
 * */
export function TableFoot({ children,rheight, ...other }: TableHeadProps) {
    return (
        <tfoot
            css={{
                display: "table-footer-group"
            }}
            {...other}
        >
        <TableSectionContext.Provider value={{ type: "TableFoot",
            rheight
        }}>
            {children}
        </TableSectionContext.Provider>
        </tfoot>
    );
}

//但@emotion会报错的：pseudo class ":first-child" is potentially unsafe when doing server-side rendering. Try changing it to ":first-of-type"；
